package com.shine.icis.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.ca.Encrypt;
import com.lzma.LzmaCompress;
import com.shine.cotrun.web.upload.FileUtil;


/**
 * 
 * @author zhangxr 2010-01-04
 */
public class FileHelper {
	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
	private static long lastTime;
	
	/**
	 * 生成不重复的号
	 * @return
	 */
	public synchronized static String createNo() {
		long l = System.currentTimeMillis();
		if (l <= lastTime) {
			lastTime = lastTime +1;
			l = lastTime;
		} else {
			lastTime = l;
		}
		return sdf.format(new Date(l));
	}
	
	/**
	 * 压缩、加密、生成清单文件
	 * @param targetFile
	 * @param pin
	 * @param cerPath
	 * @param fileName
	 * @throws Exception
	 */
	public static void submitFile(String sourcePath, String savePath, String pin ,String cerPath, 
			String fileName, boolean increment, boolean isEncrypt, String rdyFilename) throws Exception {
		//1.清空旧文件
		boolean isToFtp = FTPHelper.isFtpPath(savePath);
		String dirName = fileName.split("_")[2];
		try {//删除失败不影响下面操作，只是有可能多了些垃圾文件
			if (isToFtp) {//删除FTP上文件
				FTPHelper.delFiles(savePath, dirName);
			} else {//删除目录下文件
				FileUtil.delFiles(new File(savePath, dirName));
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		//2.处理增量
		String[] key_list_File = null;
		if (isEncrypt) {//加密增量
			key_list_File = encrypt(sourcePath, pin, cerPath, fileName, true);
		}
		//上传增量
		moveFiles(sourcePath, savePath, fileName, key_list_File, true , isEncrypt);
		
		//3.处理全量
		if (!increment) {
			if (isEncrypt) {//加密全量
				key_list_File = encrypt(sourcePath, pin, cerPath, fileName, false);
			}
			//上传全量
			moveFiles(sourcePath, savePath, fileName, key_list_File, false , isEncrypt);
		}
		
		//4.生成PFX标志文件
		if (rdyFilename != null && !rdyFilename.trim().equals("")) {
			if (isToFtp) {
				FTPHelper.createNewFile(savePath, dirName, rdyFilename);
			} else {
				File f = new File(savePath, dirName + "/" + rdyFilename);
				f.createNewFile();
			}
		}
		
	}
	
	private static String[] encrypt(String targetPath, String pin ,String cerPath, String fileName, boolean increment) throws Exception {
		String[] temArr = fileName.split("_");
		String companyCode = temArr[1];//从文件名截取券商代码
		String busiDate = temArr[2];//从文件名截取业务日期
		String targetDirStr = targetPath + "/";//数据文件存放的目录
		
		String[] key_list_File = new String[2];//KEY文件与LIST文件
		StringBuffer encodeKey = new StringBuffer(targetDirStr);//加密后密钥文件名
		encodeKey.append("SC_").append(companyCode).append("_").append(createNo()).append(".KEY");
		key_list_File[0] = encodeKey.toString();
		key_list_File[1] = key_list_File[0].replace(".KEY", ".LIST");
		
		
		
		File orgKeyPFile =  new File(targetPath, "aeskey.ORG");//定义明文密钥路径
		if (orgKeyPFile.exists()) {
			orgKeyPFile.delete();
		}
		String orgKeyPath = orgKeyPFile.getPath();
		Encrypt e = new Encrypt();
		String result = e.createkey(orgKeyPath);//
		if (result.startsWith("Error")) {
			throw new Exception("加密密钥创建失败,原因：" + result);
		}
		File[] finalFiles = new File[13];//加密后文件列表
		for (int i = 1; i <= 13; i++) { 
			String fileCode = "A" + (i < 10 ? "0" : "") + i;
			String srcPath = targetDirStr + fileName.replaceAll("@fileCode", fileCode).replaceAll("@increment", increment ? "Z" : "Q");
			finalFiles[i - 1] = comAndEnc(srcPath, orgKeyPath);
		}
		
		
		//3.加密密钥文件
		result = e.caEncode(pin, orgKeyPath, cerPath, key_list_File[0]);
		if (!result.equals("0")) {
			throw new Exception("密钥加密失败："+result);
		}
//		
//		new File(encodeKey.toString()).createNewFile();
		
		//4.生成清单文件
		BufferedWriter fw = null;
		try {
			File f = new File(key_list_File[1]);
			if (f.exists()) {
				f.delete();
			}
			f.createNewFile();
			fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), "utf-8"));
			for (int i = 0; i < finalFiles.length; i++) {
				StringBuffer row = new StringBuffer();
				row.append(finalFiles[i].getName()).append("|").append(busiDate).append("|").append(formatFileSize(finalFiles[i].length()));
				fw.write(row.toString());
				fw.write(0x0A);
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			try {
				fw.close();
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		}
		return key_list_File;
	}
	
	/**
	 * 格式化文件大小
	 * @param size
	 * @return
	 */
	private static String formatFileSize(long size) {
//		long tem = size / 1024 / 1024;
//		return tem + "M";
		return Long.toString(size);
	}
	
	/**
	 * 压缩、加密文件
	 * @param srcPath
	 * @param orgKey
	 * @return 加密后文件大小
	 * @throws Exception
	 */
	private static File comAndEnc(String srcPath, String orgKeyPath) throws Exception {
		//1.压缩文件
		LzmaCompress lc = new LzmaCompress();
		String comPath = srcPath.replace(".TXT","_YN.7Z");//压缩后保存路径
		String result = lc.compress(srcPath, comPath);
		if(!result.trim().equals("0")){   
			throw new Exception("文件压缩失败：" + result);
		}
		//2.加密文件
		Encrypt e = new Encrypt();
		String encPath = srcPath.replace(".TXT","_YA.7Z");//加密后保存路径
		result = e.buildAesDeal(orgKeyPath, comPath, encPath);
		if(!result.equals("0")){
			throw new Exception("文件加密失败：" + result);
		}
		return new File(encPath);
	}
	
	/**
	 * 移动文件夹
	 * @param targetDir
	 * @param toDir
	 * @param buffer
	 * @throws Exception
	 */
	private static void moveFiles(String sourceDir, String savePath, String fileName, 
			String[] key_list_File,  boolean increment , boolean isEncrypt) throws Exception {
		List<String> subFiles = new ArrayList<String>(15);//要上传的文件列表
		for (int i = 1; i <= 13; i++) { 
			String fileCode = "A" + (i < 10 ? "0" : "") + i;
			String srcPath = sourceDir + "/" + fileName.replaceAll("@fileCode", fileCode).replaceAll("@increment", increment ? "Z" : "Q");
			if (isEncrypt) {//如果加密，取加密后文件
				subFiles.add(srcPath.replace(".TXT", "_YA.7Z"));
			} else {
				subFiles.add(srcPath);
			}
		}
		if (isEncrypt) {//如果加密，还要多报两个文件
			subFiles.add(key_list_File[0]);
			subFiles.add(key_list_File[1]);
		}
		
		
		//开始上传
//		String dirName = fileName.split("_")[2] + "_" + (increment ? "Z" : "Q");//从文件名截取数据日期作为目录
		String dirName = fileName.split("_")[2];
		if (FTPHelper.isFtpPath(savePath)) {//上传到FTP
			FTPHelper.uploadToFTP(savePath, dirName, sourceDir);
		} else {//移到报送目录
			for (String file : subFiles) {
				File f = new File(file);
				if (!f.exists()) {
					continue;
				}
				FileUtil.copyFile(f, new File(savePath, dirName + "/" + f.getName()), 1024*100);
			}
		}
		
		
		//如果有加密则删除临时文件
		if (isEncrypt) {
			File dir = new File(sourceDir);
			File[] fs = dir.listFiles();
			if (fs == null || fs.length == 0) {
				return;
			}
			for (File f : fs) {
				if(!f.getName().endsWith(".TXT")){
					f.delete();
				}
			}
		}
	}
}


